﻿#define L1

using myAC.Configuration;
using myAC.DataProviders;
using myAC.FeatureVector;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;



namespace myAC.TLC
{
    public class InputFileGenerator
    {
        static List<String> classLabels; // SupportTopicDerivedId sequence number ~ class#



        /// <summary>
        /// Iterate through data instnaces and generate a txt input file for TLC.
        /// _SRNumber   Label   FeatureCount  "TextFeatures DTVs"  OtherFeatures
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="instances"></param>
        public static void GenerateInputData(ACInstance[] insts, String filePath, Dictionary<Int32, Int32>[] DTVs, String[] otherFeatureFilter, Int32 totalFeatureCount, DTVHelper dtvHelper, Config cfg)
        {
            classLabels = GetLabels(insts);
            StringBuilder sb = new StringBuilder();
            filePath = DateTime.Now.Ticks.ToString() + "." + filePath;
            Int32 lineCount = 0;

            if (insts.Length != DTVs.Length)
            {
                Console.WriteLine("Fatal!  instance# != DTVs#");
                return;
            }
            

            Int32 instCount = insts.Length;
            String[] selectedOtherFeatureKeys = insts[0].OtherFeatures.Keys.Where(key => otherFeatureFilter.Contains(key)).ToArray();
            Int32 otherFeatureStartIndex = dtvHelper.id_term.Count();

            for (Int32 i = 0; i < instCount; i++)
            {
                ACInstance inst = insts[i];

                String name = String.Format("_{0}", inst.InstanceName);
                String callCode=callCodeFunc2(inst);
                String label = classLabels.IndexOf(callCode).ToString(); // the label must be 0 - (N-1), where N is the total number of labels.
                sb.Append(name);
                sb.Append("\t");
#if DEBUG
                sb.Append(String.Format("{0}-[{1}]", label, callCode));
#else
                sb.Append(label);
#endif
                sb.Append("\t");

                sb.Append(totalFeatureCount);
                sb.Append("\t");

                Dictionary<Int32, Int32> dtv = DTVs[i];

                foreach(var pair in dtv)
                {
#if DEBUG
                    String dtvElement = String.Format(@"{0}-[{1}]:{2}", pair.Key, dtvHelper.id_term[pair.Key], pair.Value);
#else
                    String dtvElement = String.Format(@"{0}:{1}", pair.Key, pair.Value);
#endif
                    sb.Append(dtvElement);
                    sb.Append("\t");
                }

                if (!cfg.TextFeatureOnly)
                {
                    Int32 otherFeatureIndexOffset = 0;
                    foreach (String key in selectedOtherFeatureKeys)
                    {
                        String featureValue = inst.OtherFeatures[key].ToString();
#if DEBUG
                        sb.Append(String.Format(@"{0}-[{1}]:{2}", otherFeatureStartIndex + otherFeatureIndexOffset, key, featureValue)); //Other feature just follow the DTV elements. The index begins with the DTV element amount.

#else
                        sb.Append(String.Format(@"{0}:{1}", otherFeatureStartIndex + otherFeatureIndexOffset, featureValue)); //Other feature just follow the DTV elements. The index begins with the DTV element amount.

#endif
                        sb.Append("\t");
                        otherFeatureIndexOffset++;
                    }
                }

                sb.Append("\r\n");

                lineCount++;
                if (lineCount == 50)
                {
                    File.AppendAllText(filePath, sb.ToString());
                    sb.Clear();
                    lineCount = 0;
                }
            }

            if (lineCount > 0)
            {
                File.AppendAllText(filePath, sb.ToString());
            }
        }

        static Func<myAC.DataProviders.ACInstance, SupportTopic> topicFunc = inst => (SupportTopic)(inst.OtherFeatures["Topic"]);

#if L1
        static Func<myAC.DataProviders.ACInstance, String> callCodeFunc2 = inst => topicFunc(inst).CallCodeIdAtDifferentLevels[0];
#elif L2
        static Func<myAC.DataProviders.ACInstance, String> callCodeFunc2 = inst => topicFunc(inst).CallCodeIdAtDifferentLevels[1];
#else
        static Func<myAC.DataProviders.ACInstance, String> callCodeFunc2 = inst => topicFunc(inst).CallCodeIdAtDifferentLevels[2];
#endif

        private static List<String> GetLabels(ACInstance[] insts)
        {
            List<String> labelSet = insts.GroupBy(callCodeFunc2).Select(group => group.Key).ToList();
            Console.WriteLine("Total labels count: {0}", labelSet.Count());
            return labelSet;  // the topics which have no SRs is not included here.
        }
    }
}
